#pragma once
#include <netinet/in.h>
#include <netinet/tcp.h>
#include"Channel.h"
#include"Connection.h"
#include"InetAddress.h"
#include"Socket.h"
#include"Callback.h"
#include"Core.h"
namespace wjc {
    using namespace net;
    class Connector:public std::enable_shared_from_this<Connector>
    {
    public:
        typedef std::function<void(int sockfd)> NewConnectionCallback;

        Connector(Core* core, const InetAddress& serverAddr);
        ~Connector();

        void setNewConnectionCallback(const NewConnectionCallback& cb)
        {
            newConnectionCallback_ = cb;
        }

        void start();  // can be called in any thread
        void restart();  // must be called in loop thread
        void stop();  // can be called in any thread

        const InetAddress& serverAddress() const { return serverAddr_; }

    private:
        enum States { kDisconnected, kConnecting, kConnected };
        static const int kMaxRetryDelayMs = 30 * 1000;
        static const int kInitRetryDelayMs = 500;

        void setState(States s) { state_ = s; }
        void connect();
        void connecting(int sockfd);
        void handleWrite();
        void handleError();
        void retry(int sockfd);
        int removeAndResetChannel();
        void resetChannel();

        Core* core_;
        InetAddress serverAddr_;
        bool connect_; // atomic
        States state_;  // FIXME: use atomic variable
        std::unique_ptr<Channel> channel_;
        NewConnectionCallback newConnectionCallback_;
        int retryDelayMs_;
    };
}
